using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Terra.Core.Common.Enums.Logging;
using Terra.Core.Common.Models.Pagination;
using Terra.Data.Context;
using Terra.Data.Entities.Logging;
using Terra.Data.Extensions;
using Terra.Data.Models.Loggings;

namespace Terra.Data.Repository.Logging;

/// <summary>
/// 异常日志仓储实现
/// </summary>
public class ExceptionLogRepository : RepositoryBase<ExceptionLog, Guid>, IExceptionLogRepository
{
    private readonly TerraDbContext _context;

    /// <summary>
    /// 构造函数
    /// </summary>
    /// <param name="context">数据库上下文</param>
    public ExceptionLogRepository(TerraDbContext context) : base(context)
    {
        _context = context;
    }

    /// <inheritdoc/>
    public async Task<ExceptionLog> LogAsync(ExceptionLog log)
    {
        await _context.ExceptionLogs.AddAsync(log);
        await _context.SaveChangesAsync();
        return log;
    }

    /// <inheritdoc/>
    public async Task<IPagedList<ExceptionLog>> GetPagedListAsync(ExceptionQueryDto query)
    {
        var queryable = _dbSet.AsNoTracking();

        // 应用查询条件
        if (query.StartTime.HasValue)
        {
            queryable = queryable.Where(x => x.ExceptionTime >= query.StartTime.Value);
        }

        if (query.EndTime.HasValue)
        {
            queryable = queryable.Where(x => x.ExceptionTime <= query.EndTime.Value);
        }

        if (!string.IsNullOrEmpty(query.ExceptionType))
        {
            queryable = queryable.Where(x => x.ExceptionType.Contains(query.ExceptionType));
        }

        if (query.Severity.HasValue)
        {
            queryable = queryable.Where(x => x.Severity == query.Severity.Value);
        }

        if (!string.IsNullOrEmpty(query.RequestPath))
        {
            queryable = queryable.Where(x => x.RequestPath.Contains(query.RequestPath));
        }

        if (!string.IsNullOrEmpty(query.TraceId))
        {
            queryable = queryable.Where(x => x.TraceId == query.TraceId);
        }

        if (!string.IsNullOrEmpty(query.ExceptionMessage))
        {
            queryable = queryable.Where(x => x.ExceptionMessage.Contains(query.ExceptionMessage));
        }

        if (!string.IsNullOrEmpty(query.IpAddress))
        {
            queryable = queryable.Where(x => x.IpAddress == query.IpAddress);
        }

        // 应用排序
        queryable = queryable.OrderByDescending(x => x.ExceptionTime);

        // 创建分页结果
        return await PagedList<ExceptionLog>.CreateAsync(queryable, query.PageIndex, query.PageSize);
    }

    /// <inheritdoc/>
    public async Task<List<ExceptionStatsDto>> GetExceptionStatsAsync(DateTime? startTime, DateTime? endTime)
    {
        var query = _dbSet.AsNoTracking();

        if (startTime.HasValue)
        {
            query = query.Where(x => x.ExceptionTime >= startTime.Value);
        }

        if (endTime.HasValue)
        {
            query = query.Where(x => x.ExceptionTime <= endTime.Value);
        }

        return await query
            .GroupBy(x => new { x.Severity, Date = x.ExceptionTime.Date })
            .Select(g => new ExceptionStatsDto
            {
                Severity = g.Key.Severity,
                Date = g.Key.Date,
                Count = g.Count(),
                TenantId = g.First().TenantId
            })
            .OrderBy(x => x.Date)
            .ThenBy(x => x.Severity)
            .ToListAsync();
    }

    /// <inheritdoc/>
    public async Task<int> CleanAsync(DateTime beforeTime)
    {
        return await _dbSet
            .Where(x => x.ExceptionTime < beforeTime)
            .ExecuteDeleteAsync();
    }

    /// <inheritdoc/>
    public async Task<int> BatchDeleteAsync(IEnumerable<Guid> ids)
    {
        return await _dbSet
            .Where(x => ids.Contains(x.Id))
            .ExecuteDeleteAsync();
    }

    /// <inheritdoc/>
    public async Task<List<ExceptionLog>> ExportAsync(ExceptionQueryDto query)
    {
        var queryable = _dbSet.AsNoTracking();

        // 应用查询条件
        if (query.StartTime.HasValue)
        {
            queryable = queryable.Where(x => x.ExceptionTime >= query.StartTime.Value);
        }

        if (query.EndTime.HasValue)
        {
            queryable = queryable.Where(x => x.ExceptionTime <= query.EndTime.Value);
        }

        if (!string.IsNullOrEmpty(query.ExceptionType))
        {
            queryable = queryable.Where(x => x.ExceptionType.Contains(query.ExceptionType));
        }

        if (query.Severity.HasValue)
        {
            queryable = queryable.Where(x => x.Severity == query.Severity.Value);
        }

        // 按时间降序排序
        queryable = queryable.OrderByDescending(x => x.ExceptionTime);

        return await queryable.ToListAsync();
    }

    // 添加新方法，用于前端统计展示
    /// <summary>
    /// 获取前端统计数据
    /// </summary>
    /// <param name="startTime">开始时间</param>
    /// <param name="endTime">结束时间</param>
    /// <returns>按日期分组的异常统计</returns>
    public async Task<List<ExceptionStatsFrontendDto>> GetFrontendStatsAsync(DateTime? startTime, DateTime? endTime)
    {
        // 使用默认值：过去7天
        var defaultStartTime = DateTime.Now.AddDays(-7).Date;
        var defaultEndTime = DateTime.Now.Date.AddDays(1).AddSeconds(-1);

        var effectiveStartTime = startTime ?? defaultStartTime;
        var effectiveEndTime = endTime ?? defaultEndTime;

        var query = _dbSet.AsNoTracking();
        query = query.Where(x => x.ExceptionTime >= effectiveStartTime && x.ExceptionTime <= effectiveEndTime);

        // 获取原始统计数据
        var statsData = await query
            .GroupBy(x => new { x.Severity, Date = x.ExceptionTime.Date })
            .Select(g => new
            {
                Severity = g.Key.Severity,
                Date = g.Key.Date,
                Count = g.Count()
            })
            .ToListAsync();

        // 获取日期范围内所有日期
        var dates = new List<DateTime>();
        for (var date = effectiveStartTime.Date; date <= effectiveEndTime.Date; date = date.AddDays(1))
        {
            dates.Add(date);
        }

        // 转换为前端需要的格式
        var result = dates
            .OrderByDescending(date => date)  // 倒序排列，最近日期在前
            .Select(date => new ExceptionStatsFrontendDto
            {
                Date = date.ToString("yyyy-MM-dd"),
                Severity0Count = statsData.Where(s => s.Date == date && s.Severity == ExceptionSeverity.Warning).Sum(s => s.Count),
                Severity1Count = statsData.Where(s => s.Date == date && s.Severity == ExceptionSeverity.Error).Sum(s => s.Count),
                Severity2Count = statsData.Where(s => s.Date == date && s.Severity == ExceptionSeverity.Critical).Sum(s => s.Count),
                Severity3Count = statsData.Where(s => s.Date == date && s.Severity == ExceptionSeverity.Critical).Sum(s => s.Count)
            })
            .ToList();

        return result;
    }
}